# ๐Ÿ’š 04. ์ŠคํŠธ๋ฆผ(Stream) ํ™œ์šฉ | slice | map | match | find | reduce | ...

๐Ÿคจ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•ด๋ณด์ž! ๋จผ์ €, DISH ํด๋ž˜์Šค์™€ MainMethod๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์ž.

# ๐Ÿฝ๏ธ DISH ํด๋ž˜์Šค

package javaStudy;

public class Dish {

    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {
        MEAT,
        FISH,
        OTHER
    }

    @Override
    public String toString() {
        return "Dish{" +
                "name='" + name + '\'' +
                ", vegetarian=" + vegetarian +
                ", calories=" + calories +
                ", type=" + type +
                '}';
    }
}
package javaStudy.mda05;

import javaStudy.Dish;

import java.util.Arrays;
import java.util.List;

public class MainMethod {

    public static List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH)
    );
    
    public static void main(String[] args) {
        
    }
}

# ๐Ÿ’Ž ํ•„ํ„ฐ๋ง

์ŠคํŠธ๋ฆผ ์ธํ„ฐํŽ˜์ด์Šค๋Š” filter ๋ฉ”์†Œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. Predicate๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„์„œ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

// [Dish{name='french fries', vegetarian=true, calories=530, type=OTHER}, Dish{name='rice', vegetarian=true, calories=350, type=OTHER}, Dish{name='season fruit', vegetarian=true, calories=120, type=OTHER}, Dish{name='pizza', vegetarian=true, calories=550, type=OTHER}]
List<Dish> vegetarianMenu = menu.stream().filter(Dish::isVegetarian).collect(toList());

# ๊ณ ์œ  ์š”์†Œ๋กœ ํ•„ํ„ฐ๋ง


๊ณ ์œ  ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ง„ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” distinct ๋ฉ”์†Œ๋“œ๋„ ์ง€์›ํ•œ๋‹ค.

//2
//4
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        numbers.stream()
                .filter(i -> i % 2 == 0)
                .distinct()
                .forEach(System.out::println);

# ๐Ÿ’Ž ์ŠคํŠธ๋ฆผ ์Šฌ๋ผ์ด์‹ฑ

Java 9 ์€ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก takeWhile dropWhile ๋‘๊ฐ€์ง€ ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค.

# takeWhile


์ด๋ฏธ ์ •๋ ฌ๋œ List๋ฅผ ํ•„ํ„ฐ๋งํ•˜์˜€์„ ๊ฒฝ์šฐ, ๋ฐ˜๋ณต ์ž‘์—…์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ takeWhile์ด๋‹ค. ์ฐธ์ด ๋˜๋Š” ์š”์†Œ๊นŒ์ง€๋งŒ ํฌํ•จํ•˜๋„๋ก ํ•œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ, ์นผ๋กœ๋ฆฌ ์ˆœ์œผ๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ํ™•์ธํ•˜์—ฌ 400์นผ๋กœ๋ฆฌ ์ดํ•˜์ผ๋•Œ๊นŒ์ง€๋งŒ ์ŠคํŠธ๋ฆผ์„ ํฌํ•จํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

List<Dish> specialMenu = Arrays.asList(
                new Dish("season fruit", true, 120, Dish.Type.OTHER),
                new Dish("rice", true, 350, Dish.Type.OTHER),
                new Dish("chicken", false, 400, Dish.Type.MEAT),
                new Dish("salmon", false, 450, Dish.Type.FISH),
                new Dish("french fries", true, 530, Dish.Type.OTHER),
                new Dish("beef", false, 700, Dish.Type.MEAT));

//[Dish{name='season fruit', vegetarian=true, calories=120, type=OTHER}, Dish{name='rice', vegetarian=true, calories=350, type=OTHER}]
List<Dish> slicedMenu1
        = specialMenu.stream()
					.takeWhile(dish -> dish.getCalories() < 400)
					.collect(toList());

# dropWhile


dropWhile์€ takeWhile๊ณผ ์ •๋ฐ˜๋Œ€์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ฑฐ์ง“์ด ๋˜๋Š” ์ง€์ ๊นŒ์ง€ ๋ฐœ๊ฒฌ๋œ ์š”์†Œ๋ฅผ ๋ฒ„๋ฆฐ๋‹ค.

// [Dish{name='chicken', vegetarian=false, calories=400, type=MEAT}, Dish{name='salmon', vegetarian=false, calories=450, type=FISH}, Dish{name='french fries', vegetarian=true, calories=530, type=OTHER}, Dish{name='beef', vegetarian=false, calories=700, type=MEAT}]
List<Dish> slicedMenu2
          = specialMenu.stream()
						.dropWhile(dish -> dish.getCalories() < 400)
						.collect(toList());

# ์ŠคํŠธ๋ฆผ ์ถ•์†Œ


// [Dish{name='chicken', vegetarian=false, calories=400, type=MEAT}, Dish{name='salmon', vegetarian=false, calories=450, type=FISH}, Dish{name='french fries', vegetarian=true, calories=530, type=OTHER}]
List<Dish> limitDishes
          = specialMenu.stream()
            .filter(dish -> dish.getCalories() > 350)
            .limit(3) // 3๊ฐœ ๋ฐ˜ํ™˜
            .collect(toList());

# ์š”์†Œ ๊ฑด๋„ˆ๋›ฐ๊ธฐ


// [Dish{name='french fries', vegetarian=true, calories=530, type=OTHER}, Dish{name='beef', vegetarian=false, calories=700, type=MEAT}]
List<Dish> skipDishes
          = specialMenu.stream()
	          .filter(dish -> dish.getCalories() > 350)
	          .skip(2) // ์ฒ˜์Œ 2๊ฐœ ์š”์†Œ ์ œ์™ธํ•˜๊ณ  ๋ฐ˜ํ™˜
	          .collect(toList());

# ๐Ÿ’Ž ๋งคํ•‘ (map)

ํŠน์ • ๊ฐ์ฒด์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜๋Š” ์ž‘์—…! ์ž์ฃผ ์ˆ˜ํ–‰๋˜๋Š” ์—ฐ์‚ฐ์ด๋ฏ€๋กœ ์œ ์šฉํ•  ๊ฑฐ ๊ฐ™๋‹ค.

# ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์š”์†Œ์— ํ•จ์ˆ˜ ์ ์šฉ


๊ฐ ์š”์†Œ์— ์ ์šฉํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ƒˆ๋กœ์šด ์š”์†Œ๋กœ ๋งคํ•‘๋œ๋‹ค.

// [pork, beef, chicken, french fries, rice, season fruit, pizza, prawns, salmon]
List<String> dishNames
                = menu.stream()
	                .map(Dish::getName)
	                .collect(toList());

// [4, 4, 7, 12, 4, 12, 5, 6, 6]
List<Integer> dishNameLengths
                = menu.stream()
	                .map(Dish::getName)
	                .map(String::length)
	                .collect(toList());

# ์ŠคํŠธ๋ฆผ ํ‰๋ฉดํ™”


List์—์„œ ๊ณ ์œ ๋ฌธ์ž๋กœ ์ด๋ฃจ์–ด์ง„ List๋ฅผ ๋ฐ˜ํ™˜ํ•ด๋ณด์ž.

์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.


List<String> words = Arrays.asList("Hello", "world");
List<String[]> distinct
							= words.stream()
					      .map(s -> s.split(""))
					      .distinct()
					      .collect(toList());

ํ•˜์ง€๋งŒ ์œ„ ๋ฐฉ๋ฒ•์€ Stream<String[]> ์„ ๋ฐ˜ํ™˜ํ•  ๋ฟ๋”๋Ÿฌ Hello ์™€ World ๋กœ String[]์ด ๋‹ด๊ฒจ ๊ณ ์œ ๋ฌธ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋„ ์•Š๋Š”๋‹ค... ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์€ Stream<String> ์ด๋‹คใ… ใ… 

# map๊ณผ Arrays.stream (opens new window) ํ™œ์šฉ


๋ฌธ์ž์—ด์„ ๋ฐ›์•„ Stream์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” Arrays.stream()๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.

String[] arrayOfWords = {"Goodbye", "World"};
Stream<String> streamOfwords = Arrays.stream(arrayOfWords);

List<String> words = Arrays.asList("Hello", "world");
List<Stream<String>> distinct
							= words.stream()
					      .map(s -> s.split(""))
								.map(Arrays::stream)
					      .distinct()
					      .collect(toList());

ํ•˜์ง€๋งŒ ์œ„ ๋ฉ”์†Œ๋“œ๋„ List<Stream<String>>์ด ๋งŒ๋“ค์–ด์ ธ์„œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค.

# flapMap


flatMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ!

// [H, e, l, o, w, r, d]
List<String> distinct =
                words.stream()
                .map(s -> s.split(""))
                .flatMap(Arrays::stream)// ์ƒ์„ฑ๋œ ์ŠคํŠธ๋ฆผ์„ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ํ‰๋ฉดํ™”
                .distinct()
                .collect(toList());

# ๐Ÿ’Ž ๊ฒ€์ƒ‰๊ณผ ๋งค์นญ

ํŠน์ • ์†์„ฑ์ด ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

# anyMatch()


Predicate๊ฐ€ ์ฃผ์–ด์ง„ ์ŠคํŠธ๋ฆผ์—์„œ ์ ์–ด๋„ ํ•œ ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

if (menu.stream().anyMatch(Dish::isVegetarian)) {
    System.out.println("The menu is vegetarian friendly");
}

# allMatch()


๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ Predicate์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

// true
boolean isHealthy = menu.stream()
                        .allMatch(dish -> dish.getCalories() < 1000);

# noneMatch()


allMatch์™€ ๋ฐ˜๋Œ€๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ์œ„ ๋ฉ”์†Œ๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹ค์‹œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

// true
boolean isHealthy = menu.stream()
                        .noneMatch(dish -> dish.getCalories() >= 1000);

# findAny()


ํ˜„์žฌ ์ŠคํŠธ๋ฆผ์—์„œ ์ผ์น˜ํ•˜๋Š” ์ž„์˜์˜ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Optional<Dish> dish = menu.stream()
                      .filter(Dish::isVegetarian)
                      .findAny();

# findFirst()


์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

List<Integer> someNumbers = Arrays.asList(1,2,3,4,5);
Optional<Integer> firstSquareDivisibleByThree =
        someNumbers.stream()
                .map(n -> n * n)
                .filter(n -> n % 3 == 0)
                .findFirst();

# ๐Ÿ’Ž ๋ฆฌ๋“€์‹ฑ (Reduce)

"๋ฉ”๋‰ด์˜ ๋ชจ๋“  ์นผ๋กœ๋ฆฌ์˜ ํ•ฉ๊ณ„๋ฅผ ๊ตฌํ•˜์‹œ์˜ค" ๊ฐ™์ด ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ์กฐํ•ฉํ•ด์„œ ๋” ๋ณต์žกํ•œ ์งˆ์˜๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

# ์š”์†Œ์˜ ํ•ฉ/๊ณฑ


reduce ๋Š” 2๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค.

๐Ÿ“Œ ์ดˆ๊นƒ๊ฐ’ 0

๐Ÿ“Œ ๋‘ ์š”์†Œ๋ฅผ ์กฐํ•ฉํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฐ’์„ ๋งŒ๋“œ๋Š” BinaryOperator<T> ์˜ˆ์ œ์—์„œ๋Š” ๋žŒ๋‹คํ‘œํ˜„์‹ ์‚ฌ์šฉ

List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5);
int sum = numberList.stream().reduce(0, (a, b) -> a + b); // 15
int product = numberList.stream().reduce(1, (a, b) -> a * b); // 120

# ์ตœ๋Œ“๊ฐ’/์ตœ์†Ÿ๊ฐ’


์ดˆ๊นƒ๊ฐ’์„ ๋ฐ›์ง€ ์•Š๋„๋ก ์˜ค๋ฒ„๋กœ๋“œ๋œ reduce๋„ ์žˆ๋‹ค. ์ด reduce๋Š” Optional๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Optional<Integer> max = numberList.stream().reduce(Integer::max); // Optional[5]
Optional<Integer> min= numberList.stream().reduce(Integer::min); // Optional[1]

# ๐Ÿ’Ž ์ˆซ์žํ˜• ์ŠคํŠธ๋ฆผ

์ŠคํŠธ๋ฆผ ์š”์†Œ์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

int calories = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);

์‚ฌ์‹ค ์œ„ ์ฝ”๋“œ์—๋Š” ๋ฐ•์‹ฑ ๋น„์šฉ์ด ์ˆจ๊ฒจ์ ธ ์žˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์ „์— Integer๋ฅผ ๊ธฐ๋ณธํ˜•์œผ๋กœ ์–ธ๋ฐ•์‹ฑํ•ด์•ผํ•œ๋‹ค. ์ง์ ‘ .sum() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ์ข‹์ง€ ์•Š์„๊นŒ?

๋‹คํ–‰ํžˆ๋„ ์ˆซ์ž ์ŠคํŠธ๋ฆผ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณตํ•œ๋‹ค.

# ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ


Java 8 ์—์„œ๋Š” IntStream DoubleStream LongStream ์„ธ๊ฐ€์ง€ ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณตํ•œ๋‹ค.

๐Ÿ“Œ ์ˆซ์ž ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งคํ•‘

int calories = menu.stream()
                .mapToInt(Dish::getCalories) //IntStream
                .sum();

๐Ÿ“Œ ๊ฐ์ฒด ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณต์›ํ•˜๊ธฐ

  • ์ˆซ์ž ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“  ๋‹ค์Œ์— ์›์ƒํƒœ์ธ ํŠนํ™”๋˜์ง€ ์•Š์€ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋‹ค.
IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
Stream<Integer> stream = intStream.boxed();

๐Ÿ“Œ ๊ธฐ๋ณธ๊ฐ’: OptionalInt

  • ํ•ฉ๊ณ„ ์˜ˆ์ œ์—์„œ๋Š” 0์ด๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ์œผ๋ฏ€๋กœ ๋ณ„ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์ตœ๋Œ“๊ฐ’ ์˜ˆ์ œ์—์„œ๋Š” ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋„์ถœ๋  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋•Œ, ๊ฐ’์ด ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ ํด๋ž˜์Šค Optional์„ ํ™œ์šฉํ•œ๋‹ค. OptionalInt OptionalDouble OptionalLong ์„ธ๊ฐ€์ง€ ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ ๋ฒ„์ „๋„ ์ œ๊ณตํ•œ๋‹ค.
OptionalInt maxCalories = menu.stream().mapToInt(Dish::getCalories).max();
int max = maxCalories.orElse(1); // ๊ฐ’์ด ์—†์„ ๋•Œ ๊ธฐ๋ณธ ์ตœ๋Œ“๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •

๐Ÿ“Œ ์ˆซ์ž ๋ฒ”์œ„

  • ํŠน์ • ๋ฒ”์œ„์˜ ์ˆซ์ž๋„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. IntStream๊ณผ LongStream์—์„œ๋Š” range์™€ rangeClosed๋ผ๋Š” ๋‘๊ฐ€์ง€ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ฒซ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์‹œ์ž‘๊ฐ’์„, ๋‘๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ข…๋ฃŒ๊ฐ’์„ ๊ฐ–๋Š”๋‹ค.
IntStream evenNumbers = IntStream.rangeClosed(1, 100).filter(n -> n % 2 == 0);

# ๐Ÿ’Ž ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜์ž.

# ๊ฐ’์œผ๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ (Stream.of)


//MODERN
//JAVA
//IN
//ACTION
Stream<String> stream = Stream.of("Modern","Java","In","Action");
stream.map(String::toUpperCase).forEach(System.out::println);
Stream<String> emptyStream = Stream.empty(); // ์ŠคํŠธ๋ฆผ์„ ๋น„์šธ ์ˆ˜ ์žˆ๋‹ค.

# null์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ (Stream.ofNullable)


๊ธฐ์กด์—๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ null์„ ๋ช…์‹œ์ ์œผ๋กœ ํ™œ์šฉํ•ด์•ผ ํ–ˆ๋‹ค.

String homeValue = System.getProperty("home");
Stream<String> homeValueStream
        = homeValue == null ? Stream.empty() : Stream.of(homeValue);

Stream.ofNullable์„ ์ด์šฉํ•ด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

Stream<String> homeValueStream
            = Stream.ofNullable(System.getProperty("home"));

# ๋ฐฐ์—ด๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ (Arrays.stream)


๊ธฐ๋ณธํ˜• int๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด์„ IntStream์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();

# ํŒŒ์ผ๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ


long uniqueWords = 0;
try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
    uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
            .distinct().count();
} catch (IOException e) {
    e.printStackTrace();
}

# ํ•จ์ˆ˜๋กœ ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ


๋ฌดํ•œ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋‘ ์ •์  ๋ฉ”์„œ๋“œ Stream.iterate Stream.generate๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๐Ÿ“Œ iterate

  • ์—ฐ์†๋œ ์ผ๋ จ์˜ ๊ฐ’์„ ๋งŒ๋“ค ๋•Œ๋Š” iterate๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
// 0
// 2
// 4
// 6
// 8
Stream.iterate(0, n -> n + 2).limit(5).forEach(System.out::println);

๐Ÿ“Œ generate

  • iterate๊ณผ ๋‹ฌ๋ฆฌ ์—ฐ์†์ ์œผ๋กœ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๊ณ , Supplier<T>๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค.
// 0.19486211698371403
// 0.31687022682444055
// 0.5129741768745474
Stream.generate(Math::random).limit(3).forEach(System.out::println);

# Reference


๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜ (ํ•œ๋น›๋ฏธ๋””์–ด)

Last Updated: 3/8/2024, 5:46:31 AM